﻿/* This code is restricted under LGPL license */
using NHibernate.Criterion;

namespace infoMECHANICA.NHibernateORM.CriteriaBuilder
{
    /// <summary>
    /// Property convertible into subquery criterions
    /// </summary>
    /// <typeparam name="T">Inner type of property (declared type of dto property being wrapped)</typeparam>
    public class SubcriteriaProperty<T> : PropertyNameHolder, ISubcriteriaSource,ISubcriteriaProperty<T> where T : ICriteriaSource
    {
        private SubqueryConjunctionTypes subqueryConjuntionType;
        private ICriteriaSource savedCriteriaSource;

        /// <summary>
        /// Saved criteria source
        /// </summary>
        protected ICriteriaSource SavedCriteriaSource
        {
            get { return savedCriteriaSource; }
            set { savedCriteriaSource = value; }
        }       

        #region ISubcriteriaProperty<T> Members
        /// <summary>
        /// <see>ISubcriteriaProperty</see> interface summary
        /// </summary>
        public void Exists(T value)
        {
            this.SubqueryConjuntionType = SubqueryConjunctionTypes.Exists;
            this.SavedCriteriaSource = value;
        }

        /// <summary>
        /// <see>ISubcriteriaProperty</see> interface summary
        /// </summary>
        public void NotExists(T value)
        {
            this.SubqueryConjuntionType = SubqueryConjunctionTypes.NotExists;
            this.SavedCriteriaSource = value;
        }

        #endregion

        #region ISubcriteriaSource Members
        /// <summary>
        /// <see>ISubcriteriaProperty</see> interface summary
        /// </summary>
        public SubqueryConjunctionTypes SubqueryConjuntionType
        {
            get { return subqueryConjuntionType; }
            set { subqueryConjuntionType = value; }
        }

        /// <summary>
        /// <see>ISubcriteriaProperty</see> interface summary
        /// </summary>
        public string MasterPropertyName
        {
            get
            {
                return this.PropertyName;
            }
        }

        /// <summary>
        /// <see>ISubcriteriaProperty</see> interface summary
        /// </summary>
        public DetachedCriteria BuildCriteria()
        {
            return this.SavedCriteriaSource.BuildCriteria();
        }

        /// <summary>
        /// <see>ISubcriteriaProperty</see> interface summary
        /// </summary>
        public DetachedCriteria BuildCriteria(string alias)
        {
            return this.SavedCriteriaSource.BuildCriteria(alias);
        }

        /// <summary>
        /// <see>ISubcriteriaProperty</see> interface summary
        /// </summary>
        public bool HasCriteria()
        {
            return ((this.SavedCriteriaSource != null) && (this.SubqueryConjuntionType != SubqueryConjunctionTypes.None));
        }

        #endregion

        /// <summary>
        /// Constructor, sets MasterPropertyName
        /// </summary>
        /// <param name="masterPropertyName">Master's object property name</param>
        public SubcriteriaProperty(string masterPropertyName)
            : base(masterPropertyName)
        {
            this.SubqueryConjuntionType = SubqueryConjunctionTypes.None;
        }
    }
}
